package xian.woniuxy.zh_generic.h;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

class A {
    void f1() {

    }
}

class B extends A {
    void f2() {

    }
}

class C extends B {
    void f3() {

    }
}

class D extends C {
    void f4() {

    }
}

class E extends D {
    void f5(String a) {

    }
}

class Foo<T extends A> {

}


public class App {

    public static void f1(List<? extends C> list) {
        // 模拟多态
        /*
               一旦使用  List<? extends A> list = null;
               确实能支持向上转型，但是为了保证集合中是“同构”的，
               1. 这样的集合，里面什么元素都无法加入，只能加入null
               2. 这样的集合，只能用来读取，删除，交集，差集
               3. 既然这样的集合，能读取，那读取出来的类型只能用 上界或上界的父类 接受，或者用Object接收
         */
        C obj = list.get(0);
        Object obj2 = list.get(1);
    }

    public static void f2(List<? super C> list) {
        // 模拟多态
        /*
               一旦使用  List<? super C> list = null;
               确实能支持多态，但是为了保证集合中是“同构”的，
               1. 这样的集合， 能不能加入元素，能，能加入C（或C的子类），因为集合list，接受的集合中，统统都存放的是C的父类，C可以当做任何一个父类
         */
//        list.add(new C());
//        list.add(new D());
//        list.add(new E());

        //    2. 这样的集合，get元素以后，用什么类型获取， 只能用Object来取元素。
        Object b = list.get(0);
    }

    public static void main(String[] args) {


//        f1(new ArrayList<A>());
//        f1(new ArrayList<B>());
        f1(new ArrayList<C>());
        f1(new ArrayList<D>());
        f1(new ArrayList<E>());

//        f2(new ArrayList<Object>());
//        f2(new ArrayList<A>());
//        f2(new ArrayList<B>());
//        f2(new ArrayList<C>());
//        f2(new ArrayList<D>());
//        f2(new ArrayList<E>());

    }
    //  PECS原则：  该原则，指导我们，什么时候使用  ? extends 类型，   什么时候用  ? super 类型。
    //  producer use extends,  consumer use super.
    //  从集合中获取元素(list.get(0))，该集合就是生产者.   给集合中添加元素(list.add(new A()))，就是消费者
}
